﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using SdmxMl.Common;
using System.Text;
using System.Xml;

namespace SdmxMl.Structure
{
    /// <summary>
    /// TargetIdentifiers are the set of objects against which reference metadata is reported
    /// (data providers, data flows, data or metadata structures, etc.). There are two types of
    /// TargetIdentifiers: the "full" target identifier, which lists every object used to attach
    /// metadata to in the metadata structure definition, and the partial target identifiers,
    /// which indicate sub-sets of those concepts against which reference metadata may be reported.
    /// It is sometimes the case that metadata will also be reported against the full target identifier. 
    /// 
    /// An example of this is as follows: we might wish to collect some metadata concepts such as contact
    /// information for some of the objects described by the SDMX Information Model - for each instance
    /// of a metadata flow or a data provider, for example. Our concepts would be the concepts associated
    /// with contact information: CONTACT_NAME, CONTACT_PHONE_NUMBER, etc. We would determine how these
    /// concepts are associated with the objects in the model: do we want a contact for each data provider
    /// broken out by data flow? Or do we want only a single contact reported for each data provider
    /// (who might provide several data flows)? Each object or combination of objects we need to have
    /// metadata reported for becomes a partial target identifier, unless it happens to contain the full
    /// target identifier, in which case we use that instead. Thus, our valid partial target identifiers
    /// here would be "data flow" and "data provider", because "data flow by data provider" is a full target
    /// identifier. For each target identifier, we could have some set of our concepts reported.
    /// </summary>
    public class TargetIdentifiersType : IAnnotationList
    {
        #region Properties

        private FullTargetIdentifierType _fullTargetIdentifier;
        public FullTargetIdentifierType FullTargetIdentifier
        {
            get { return _fullTargetIdentifier; }
        }

        // SDMX 2.0 only
        private PartialTargetIdentifierTypeList _partialTargetIdentifierList;
        public PartialTargetIdentifierTypeList PartialTargetIdentifierList
        {
            get { return _partialTargetIdentifierList; }
        }

        private AnnotationList annotationList;
        public AnnotationList AnnotationList
        {
            get { return annotationList; }
            set { annotationList = value; }
        }

        #endregion //Properties

        #region Constructors

        public TargetIdentifiersType()
        {
            Init();
        }

        private void Init()
        {
            _partialTargetIdentifierList = new PartialTargetIdentifierTypeList();
            _fullTargetIdentifier = new FullTargetIdentifierType();
            AnnotationList = new AnnotationList();
        }

        public TargetIdentifiersType(XmlNode nodeArtefact, SdmxNamespaceManager nsmgr) 
        {     
            Init();

            if (nsmgr.VersionSdmx == SdmxVersion.SDMX_20)
            {
                string query = "./structure:FullTargetIdentifier";
                XmlNode nodeFull = nodeArtefact.SelectSingleNode(query, nsmgr);
                if (nodeFull != null)
                    _fullTargetIdentifier = new FullTargetIdentifierType(nodeFull, nsmgr);
                query = "./structure:PartialTargetIdentifier";
                XmlNodeList nodeList = nodeArtefact.SelectNodes(query, nsmgr);
                foreach (XmlNode nd in nodeList)
                    _partialTargetIdentifierList.Add(new PartialTargetIdentifierType(nd, nsmgr));

                nodeList = nodeArtefact.SelectNodes("./structure:Annotations/common:Annotation", nsmgr);
                foreach (XmlNode na in nodeList)
                {
                    Annotation a = new Annotation(na, nsmgr);
                    annotationList.Add(a);
                }
            }
            else // SDMX 2.1
            {
                _fullTargetIdentifier = new FullTargetIdentifierType(nodeArtefact, nsmgr);
                XmlNodeList nodeList = nodeArtefact.SelectNodes("./common:Annotations/common:Annotation", nsmgr);
                foreach (XmlNode na in nodeList)
                {
                    Annotation a = new Annotation(na, nsmgr);
                    annotationList.Add(a);
                }

            }
        }

        #endregion //Constructors

        #region XML serialize

        public void WriteXml(XmlTextWriter xw, string prefix, string tag)
        {
            xw.WriteStartElement(prefix, tag, null);

                // value required
                _fullTargetIdentifier.WriteXml(xw, prefix, "FullTargetIdentifier");

                foreach (PartialTargetIdentifierType pt in _partialTargetIdentifierList)
                    pt.WriteXml(xw, prefix, "PartialTargetIdentifier");

                // Annotations
                AnnotationList.WriteXml(xw, prefix, null);

            xw.WriteEndElement();
        }

        #endregion // XML serialize



        #region Tree
        public virtual TreeNode FillNode(TreeNode parentNode)
        {
            TreeNode t = new TreeNode(this.ToString());
            t.Tag = this;
            parentNode.Nodes.Add(t);
            return t;
        }

        #endregion // Tree

        public override string ToString()
        {
            return FullTargetIdentifier.Id;
        }

    }

    public class TargetIdentifiersTypeList : List<TargetIdentifiersType>
    {
        public override string ToString()
        {
            return "Metadata Targets";
        }
    }
}
